package com.github.cyf.common.util;

import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author chenyifan
 * @create 2024-08-07 16:37
 */
public class DateUtil {

    public static final DateTimeFormatter defaultDateTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter defaultDateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter defaultTimeFormat = DateTimeFormatter.ofPattern("HH:mm:ss");
    public static final DateTimeFormatter MF = DateTimeFormatter.ofPattern("yyyy-MM");

    private static final String[] dateTimeFormatParts = {"y", "M", "d", "H", "m", "s", "S"};
    private static final String[] timeFormatParts = {"H", "m", "s", "S"};
    private static final String DATE_FORMAT_23 = "yyyyMMddHHmmssSSSSSSSSS";
    private static final String DATE_FORMAT_15 = "HHmmssSSSSSSSSS";

    /**
     * 选择日期格式
     * @param dateString 日期字符串
     * @return
     */
    private static DateTimeFormatter switchDateFormat(String dateString) {
        if (!StringUtils.hasLength(dateString)) {
            throw new IllegalArgumentException("时间字符串为空");
        }

        // 匹配多个数字，或者多个非数字字符
        Pattern pattern = Pattern.compile("(\\d+)|([^\\d]+)");
        Matcher matcher = pattern.matcher(dateString);
        List<String> numbers = new ArrayList<>();
        List<String> delimiters = new ArrayList<>();
        while (matcher.find()) {
            String group1 = matcher.group(1);
            String group2 = matcher.group(2);
            if (StringUtils.hasLength(group1)) {
                // 匹配到的是数字部分
                numbers.add(group1);
            } else if (StringUtils.hasLength(group2)) {
                // 匹配到的是非数字部分（即分隔符）
                delimiters.add(group2);
            }
        }

        // 如果分隔符为空，根据长度选择合适的格式
        int length = dateString.length();
        if (CollectionUtils.isEmpty(delimiters)) {
            String formatStr = length <= DATE_FORMAT_23.length() ? DATE_FORMAT_23.substring(0, length) : DATE_FORMAT_23;
            return DateTimeFormatter.ofPattern(formatStr);
        }

        StringBuilder formatStr = new StringBuilder();
        // 如果包含非数字字符，则构建自定义格式
        for (int i = 0; i < numbers.size() && i < dateTimeFormatParts.length; i++) {
            String number = numbers.get(i);
            for (int j = 0; j < number.length(); j++) {
                formatStr.append(dateTimeFormatParts[i]);
            }
            if (i < delimiters.size()) {
                formatStr.append(delimiters.get(i));
            }
        }

        if (formatStr.length() <= 0) {
            throw new IllegalArgumentException("未找到合适的日期格式");
        }

        return DateTimeFormatter.ofPattern(formatStr.toString());
    }

    /**
     * 选择时间格式
     * @param timeString 时间字符串
     * @return
     */
    private static DateTimeFormatter switchTimeFormat(String timeString) {
        if (!StringUtils.hasLength(timeString)) {
            throw new IllegalArgumentException("时间字符串为空");
        }

        // 匹配多个数字，或者多个非数字字符
        Pattern pattern = Pattern.compile("(\\d+)|([^\\d]+)");
        Matcher matcher = pattern.matcher(timeString);
        List<String> numbers = new ArrayList<>();
        List<String> delimiters = new ArrayList<>();
        while (matcher.find()) {
            String group1 = matcher.group(1);
            String group2 = matcher.group(2);
            if (StringUtils.hasLength(group1)) {
                // 匹配到的是数字部分
                numbers.add(group1);
            } else if (StringUtils.hasLength(group2)) {
                // 匹配到的是非数字部分（即分隔符）
                delimiters.add(group2);
            }
        }

        // 如果分隔符为空，根据长度选择合适的格式
        int length = timeString.length();
        if (CollectionUtils.isEmpty(delimiters)) {
            String formatStr = length <= DATE_FORMAT_15.length() ? DATE_FORMAT_15.substring(0, length) : DATE_FORMAT_15;
            return DateTimeFormatter.ofPattern(formatStr);
        }

        StringBuilder formatStr = new StringBuilder();
        // 如果包含非数字字符，则构建自定义格式
        for (int i = 0; i < numbers.size() && i < timeFormatParts.length; i++) {
            String number = numbers.get(i);
            for (int j = 0; j < number.length(); j++) {
                formatStr.append(timeFormatParts[i]);
            }
            if (i < delimiters.size()) {
                formatStr.append(delimiters.get(i));
            }
        }

        if (formatStr.length() <= 0) {
            throw new IllegalArgumentException("未找到合适的日期格式");
        }

        return DateTimeFormatter.ofPattern(formatStr.toString());
    }


    // ----------------------------------- 日期格式化 --------------------------------------------

    /**
     * 格式化日期时间为 yyyy-MM-dd HH:mm:ss 格式
     * @param time LocalDateTime
     * @return
     */
    public static String format(LocalDateTime time) {
        return time.format(defaultDateTimeFormat);
    }

    /**
     * 自定义时间格式方式
     * @param dateTime LocalDateTime
     * @param pattern 日期格式
     * @return
     */
    public static String format(LocalDateTime dateTime, String pattern) {
        return dateTime.format(DateTimeFormatter.ofPattern(pattern));
    }


    /**
     * 格式化日期时间为 yyyy-MM-dd 格式
     * @param time  LocalDate
     * @return
     */
    public static String format(LocalDate time) {
        return time.format(defaultDateFormat);
    }

    /**
     * 自定义日期格式方式
     * @param date LocalDate
     * @param pattern 日期格式
     * @return
     */
    public static String format(LocalDate date, String pattern) {
        return date.format(DateTimeFormatter.ofPattern(pattern));
    }


    /**
     * 格式化日期时间为 HH:mm:ss 格式
     * @param time LocalTime
     * @return
     */
    public static String format(LocalTime time) {
        return time.format(defaultTimeFormat);
    }

    /**
     * 自定义时间格式方式
     * @param time LocalTime
     * @param pattern 日期格式
     * @return
     */
    public static String format(LocalTime time, String pattern) {
        return time.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 格式化日期时间为 yyyy-MM 格式
     * @param time
     * @return
     */
    public static String format(YearMonth time) {
        return time.format(MF);
    }

    /**
     * 自定义年月格式方式
     * @param time
     * @param pattern
     * @return
     */

    public static String format(YearMonth time, String pattern) {
        return time.format(DateTimeFormatter.ofPattern(pattern));
    }

    // -------------------------------- 日期字符串解析 -------------------------------------------

    /**
     * 解析日期字符串为 LocalDateTime
     * @param time 时间字符串
     * @return
     */
    public static LocalDateTime parseDateTime(String time) {
        // 先尝试使用默认格式解析
        try {
            return LocalDateTime.parse(time, defaultDateTimeFormat);
        } catch (Exception ignored) {
        }

        DateTimeFormatter formatter = switchDateFormat(time);
        try {
            return LocalDateTime.parse(time, formatter);
        } catch (Exception e) {
            return LocalDate.parse(time, formatter).atTime(LocalTime.MIN);
        }
    }

    /**
     * 自定义时间解析方式
     * @param time 时间字符串
     * @param pattern 日期格式
     * @return
     */
    public static LocalDateTime parseDateTime(String time, String pattern) {
        return LocalDateTime.parse(time, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 解析日期字符串为 LocalDate
     * @param time 时间字符串
     * @return
     */
    public static LocalDate parseDate(String time) {
        try {
            return LocalDate.parse(time, defaultDateFormat);
        } catch (Exception ignored) {
        }

        DateTimeFormatter formatter = switchDateFormat(time);
        try {
            return LocalDate.parse(time, formatter);
        } catch (Exception e) {
            return LocalDateTime.parse(time, formatter).toLocalDate();
        }
    }

    /**
     * 自定义日期解析方式
     * @param time 时间字符串
     * @param pattern 日期格式化器
     * @return
     */
    public static LocalDate parseDate(String time, String pattern) {
        return LocalDate.parse(time, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 解析日期字符串为 LocalTime
     * @param time 时间字符串
     * @return
     */
    public static LocalTime parseTime(String time) {
        try {
            return LocalTime.parse(time, defaultTimeFormat);
        } catch (Exception ignored) {
        }

        return LocalTime.parse(time, switchTimeFormat(time));
    }

    /**
     * 自定义日期解析方式
     * @param time 时间字符串
     * @param pattern 日期格式化器
     * @return
     */
    public static LocalTime parseTime(String time, String pattern) {
        return LocalTime.parse(time, DateTimeFormatter.ofPattern(pattern));
    }

}